#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#define TIME_NEXT 50 // 时间间隔

#define FIFO_PHONE "/tmp/phone_fifo"
#define FIFO_UI "/tmp/ui_fifo"

enum TASK_PHONE_STATE {
  TASK_PHONE_STATE_NONE = 0,
  TASK_PHONE_STATE_RING,
  TASK_PHONE_STATE_TALK,
  TASK_PHONE_STATE_HANGUP
};

int phone_state = TASK_PHONE_STATE_NONE;
int time = 0;
int fifo_phone = -1;
int fifo_ui = -1;

void next_state() {
  time = 0;
  phone_state = phone_state % 3 + 1;
  printf("Current state is %d\n", phone_state);
}

void init_fifo() {
  // phone fifo
  if (access(FIFO_PHONE, F_OK)) {
    if (-1 == mkfifo(FIFO_PHONE, 0666)) {
      perror("create fifo_phone error");
      exit(-1);
    }
  }

  // fifo_phone = open(FIFO_PHONE, O_WRONLY | O_NONBLOCK);
  fifo_phone = open(FIFO_PHONE, O_RDWR | O_NONBLOCK);

  if (fifo_phone == -1) {
    perror("open fifo_phone error\n");
    exit(-1);
  }

  // ui fifo
  if (access(FIFO_UI, F_OK)) {
    if (-1 == mkfifo(FIFO_UI, 0666)) {
      perror("create fifo_ui error!\n");
      exit(-1);
    }
  }

  // fifo_ui = open(FIFO_UI, O_WRONLY | O_NONBLOCK);
  fifo_ui = open(FIFO_UI, O_RDWR | O_NONBLOCK);

  if (fifo_ui == -1) {
    perror("open fifo_ui error\n");
    exit(-1);
  }

  puts("init fifo finished.");
}

void hangup() {
  // 给 ui 发送 phone 终止消息
  char msg[] = "phone_quit";
  write(fifo_phone, msg, strlen(msg) + 1);
  printf("Send phone quit msg...\n");
}

int main() {
  char buf[256] = {0};
  int len;

  init_fifo();

  while (true) {
    // 判断是否收到ui终止信号，如果收到则挂断
    bzero(buf, sizeof(buf));
    len = read(fifo_ui, buf, sizeof(buf));

    if (len > 0) {
      if (strcmp(buf, "ui_quit") == 0) {
        printf("Task ui hangup.\n");
        phone_state = TASK_PHONE_STATE_HANGUP;
      }
    }

    if (++time >= TIME_NEXT)
      next_state();

    // 电话挂断，得通知ui
    if (phone_state == TASK_PHONE_STATE_HANGUP) {
      hangup();
      break;
    }

    usleep(100 * 1000);
  }

  close(fifo_phone);
  close(fifo_ui);

  return 0;
}
